/*
 ============================================================================
 Name		: FEDir.cpp
 Author	  : goodsea
 Version	 : 1.0
 Copyright   : goodsea
 Description : CFEDir implementation
 ============================================================================
 */

#include "FEDir.h"
#include <f32file.h>

CFEDir::CFEDir() :
	iFs(CEikonEnv::Static()->FsSession()) //get the file server session
{
}

CFEDir::~CFEDir()
{
	if (iDirList != NULL)
	{
		delete iDirList;
	}

	if (iDirListSelf != NULL)
	{
		delete iDirListSelf;
	}

	delete iFileMan;
}

CFEDir* CFEDir::NewL()
{
	CFEDir* self = new (ELeave) CFEDir();
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
}

void CFEDir::ConstructL()
{
	iFileMan = CFileMan::NewL(iFs);
}

/*********************************************************
 * @Name:       Delete 
 * @Author:     YangYang
 * @Purpose:    Deletes a directory and all files and directories contained
 in the directory structure below it
 * @Returns:    TInt
 * @Parameters: aName--The name of the current directory including its path             
 * @Remarks:    -the files in the directory have the read-only attribute will
 not be deleted
 **********************************************************/
TInt CFEDir::Delete(const TDesC& aName)
{
	TInt err = iFileMan->RmDir(aName);

	if (err == KErrNone)
		return ETrue;
	else
		return EFalse;
}

/*********************************************************
 * @Name:       Rename 
 * @Author:     YangYang
 * @Purpose:    Rename the specified directory
 * @Returns:    TInt
 * @Parameters: anOldName--The old name of the current directory with its path  
 *              aNewName----The new name of the current directory with its path           
 * @Remarks:
 **********************************************************/
TInt CFEDir::Rename(const TDesC& anOldName, const TDesC& aNewName)
{
	TInt err = iFs.Rename(anOldName, aNewName);
	if (err == KErrNone)
		return ETrue;
	else
		return EFalse;
}

/*********************************************************
 * @Name:       Move
 * @Author:     YangYang
 * @Purpose:    Move the directory to the specified path
 * @Returns:    TInt
 * @Parameters: anOld--The old name of the current directory with its path  
 *              aNew----The new path           
 * @Remarks:
 **********************************************************/
TInt CFEDir::Move(const TDesC &anOld, const TDesC &aNew)
{
	TInt err = iFileMan->Move(anOld, aNew, CFileMan::ERecurse);

	if (err == KErrNone)
		return ETrue;
	else
		return EFalse;
}

/*********************************************************
 * @Name:       Copy
 * @Author:     YangYang
 * @Purpose:    Copy the directory to the specified path
 * @Returns:    TInt
 * @Parameters: anOld--The old name of the current directory with its path  
 *              aNew----The new path           
 * @Remarks:
 **********************************************************/
TInt CFEDir::Copy(const TDesC &anOld, const TDesC &aNew)
{
	TInt err = iFileMan->Copy(anOld, aNew, CFileMan::ERecurse);

	if (err == KErrNone)
		return ETrue;
	else
		return EFalse;
}

/*********************************************************
 * @Name:       DirectoryAttribute
 * @Author:     YangYang
 * @Purpose:    see the directory's Properties such as Hidden,ReadOnly,System 
 and so on
 * @Returns:    void
 * @Parameters: aDirectoryName--The name of the current directory with its path  
 *              aProperties----Save the properties into aProperties and other 
 one will call the function to printf to the screen         
 * @Remarks:
 **********************************************************/
void CFEDir::DirectoryAttribute(const TDesC& aDirectoryName, TDes& aProperties)
{
	TEntry entry;
	TInt err = iFs.Entry(aDirectoryName, entry);
	if (err == KErrNone)
	{
		if (entry.IsHidden())
		{
			aProperties.Append(_L("Hidden Dir\n"));
		}
		else
		{
			aProperties.Append(_L("Not Hidden Dir\n"));
		}

		if (entry.IsReadOnly())
		{
			aProperties.Append(_L("ReadOnly Dir\n"));
		}
		else
		{
			aProperties.Append(_L("Not ReadOnly Dir\n"));
		}

		if (entry.IsSystem())
		{
			aProperties.Append(_L("System Dir\n"));
		}
		else
		{
			aProperties.Append(_L("Not System Dir\n"));
		}
	}
}

/*********************************************************
 * @Name:       GetDirectorySize
 * @Author:     YangYang
 * @Purpose:    To get the directory's size
 * @Returns:    TInt
 * @Parameters: aDirectoryName--The name of the current directory with its path  
 aTotalsize--The directory's size        
 * @Remarks:    as there is no API function to get the directory's size, I only 
 can get each individual file or directory size and sum them up 
 **********************************************************/
TInt CFEDir::GetDirectorySize(const TDesC& aPath, TInt aTotalsize)
{
	TFileName fullname;
	iDirListSelf = GetDirectoryAndFileListL(iDirListSelf, aPath);
	TInt count = iDirListSelf->Count();
	for (int i = 0; i < count; i++)
	{
		if ((*iDirListSelf)[i].IsDir())
		{
			fullname.Copy(aPath);
			fullname.Append((*iDirListSelf)[i].iName);
			fullname.Append('\\');
			aTotalsize = GetDirectorySize(fullname, aTotalsize); //use recursion to get sub directory's size 
			iDirListSelf = GetDirectoryAndFileListL(iDirListSelf, aPath);//set iDirListSelf to point back to the current path
		}
		else
		{
			TInt size = (*iDirListSelf)[i].iSize;
			aTotalsize += size;
		}
	}
	return aTotalsize;
}

/*********************************************************
 * @Name:       GetDirectorySize
 * @Author:     YangYang
 * @Purpose:    To offer the interface to pass the directory's size to others
 * @Returns:    TInt
 * @Parameters: aPath--The name of current directory with its path       
 * @Remarks: 
 **********************************************************/
TInt CFEDir::GetDirSize(const TDesC& aPath)
{
	TInt size = 0;
	size = GetDirectorySize(aPath, size);
	return size;
}

/*********************************************************
 * @Name:       GetDirectoryAndFileList
 * @Author:     YangYang
 * @Purpose:    To offer the interface to pass the directory's content to others
 * @Returns:    CDir
 * @Parameters: aPath--The name of current directory with its path       
 * @Remarks: 
 **********************************************************/
CDir* CFEDir::GetDirectoryAndFileListL(const TDesC& aPath)
{
	return GetDirectoryAndFileListL(iDirList, aPath);
}

/*********************************************************
 * @Name:       GetDirectoryAndFileList
 * @Author:     YangYang
 * @Purpose:    Gets a filtered list of a directory's contents
 * @Returns:    CDir
 * @Parameters: aDirList--The directory's contents will be saved into it
 *              aPath--The name of current directory with its path       
 * @Remarks:     
 **********************************************************/
CDir* CFEDir::GetDirectoryAndFileListL(CDir* &aDirList, const TDesC& aPath)
{
	if (aDirList)
	{
		delete aDirList;
		aDirList = NULL;
	}

	TInt result = iFs.GetDir(aPath, KEntryAttNormal | KEntryAttReadOnly
			| KEntryAttHidden | KEntryAttSystem | KEntryAttVolume
			| KEntryAttDir | KEntryAttArchive | KEntryAttXIP, ESortByName
			| EDirsFirst | EAscending, aDirList);

	User::LeaveIfError(result);

	return aDirList;
}

/*********************************************************
 * @Name:       NewFolder
 * @Author:     YangYang
 * @Purpose:    Create a new directory
 * @Returns:    TInt
 * @Parameters: aName--the new directory's name      
 * @Remarks:     
 **********************************************************/
TInt CFEDir::NewFolder(const TDesC& aName)
{
	TInt err = iFs.MkDir(aName);

	if (err == KErrNone)
		return ETrue;
	else
		return EFalse;
}

// End of File
